package net.kazed.nextaction.database.serialize;

import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.LinkedList;

public class XmlWriter {

   private int indent;
   private LinkedList<String> elementStack;
   private PrintWriter writer;
   private XmlEncoder xmlEncoder;
   
   /**
    * Constructor.
    * @param writer
    */
   public XmlWriter(XmlEncoder xmlEncoder, OutputStream outputStream) {
      super();
      this.xmlEncoder = xmlEncoder;
      this.writer = new PrintWriter(outputStream);
      elementStack = new LinkedList<String>();
   }

   /**
    * Constructor.
    * @param writer
    */
   public XmlWriter(XmlEncoder xmlEncoder, PrintWriter writer) {
      super();
      this.xmlEncoder = xmlEncoder;
      this.writer = writer;
      elementStack = new LinkedList<String>();
   }

   /**
    * Add element with text value.
    * @param name Element name.
    * @param value Text value.
    */
   public void addElement(String name, String value) {
      writeIndent();
      writeStartElement(name);
      writer.print(xmlEncoder.encode(value));
      writeEndElement(name);
      writer.println();
   }

   /**
    * Add element with text value.
    * @param name Element name.
    * @param value Text value.
    */
   public void addElement(String name, int value) {
      addElement(name, Integer.toString(value));
   }

   /**
    * Add element with text value.
    * @param name Element name.
    * @param value Text value.
    */
   public void addElement(String name, boolean value) {
      addElement(name, Boolean.toString(value));
   }

   /**
    * Add element with text value.
    * @param name Element name.
    * @param value Text value.
    */
   public void addElement(String name, Object value) {
      if (value == null) {
         addElement(name, "");
      } else {
         addElement(name, value.toString());
      }
   }

   public void startElement(String name) {
      writeIndent();
      writeStartElement(name);
      writer.println();
      indent++;
      elementStack.addLast(name);
   }
   
   public void endElement() {
      if (elementStack.isEmpty()) {
         throw new IllegalStateException("no open elements in stack");
      }
      indent--;
      writeIndent();
      String name = elementStack.removeLast();
      writeEndElement(name);
      writer.println();
   }
   
   /**
    * Flush writer.
    */
   public void flush() {
      writer.flush();
   }
   
   private void writeStartElement(String name) {
      writer.print("<");
      writer.print(name);
      writer.print(">");
   }

   private void writeEndElement(String name) {
      writer.print("</");
      writer.print(name);
      writer.print(">");
   }

   private void writeIndent() {
      for (int i=0; i<indent; i++) {
         writer.write(" ");
      }
   }
   
}
